package com.nsw99.session;

import java.io.IOException;
import java.util.UUID;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.nsw99.ConfigLoader;
import com.nsw99.cache.CacheManager;
import com.nsw99.cache.redis.RedisCacheProvider;

import lombok.Setter;

/**
 * @author helin
 * @email hl_0074@sina.com
 * @date 2016年8月9日
 */
public class RedisSessionClusterFilter implements Filter {

	public static boolean SESSION_STICKY = true;

	@Setter
	private String domain;
	@Setter
	private String config = "/cluster-session.properties";

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;

		String clusterId = findClusterId(request);
		if (clusterId == null) {
			clusterId = appendClusterId(response);
		}
		RedisWarrpedRequest redisRequest = new RedisWarrpedRequest(clusterId, request);
		chain.doFilter(redisRequest, response);
		// 当session invalidate时，应当response去掉cookieid
		redisRequest.afterRequest(response);
	}

	/**
	 * @param request
	 * @return
	 */
	private String findClusterId(HttpServletRequest request) {

		String sessionId = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null && cookies.length > 0) {
			for (Cookie cookie : cookies) {
				if (RedisSession.CLUSTER_KEY.equalsIgnoreCase(cookie.getName())) { return cookie.getValue(); }
			}
		}
		return sessionId;
	}

	/**
	 * @param response
	 * @return
	 */
	private String appendClusterId(ServletResponse response) {

		String sessionId = UUID.randomUUID().toString().replace("-", "").toUpperCase();
		Cookie cookie = new Cookie(RedisSession.CLUSTER_KEY, sessionId);
		cookie.setMaxAge(-1); // 浏览器关闭时，cookie过期
		cookie.setPath("/"); // 对于 相同域名下，皆可访问
		cookie.setHttpOnly(true);
		if (domain != null) {
			cookie.setDomain(domain);
		}

		((HttpServletResponse) response).addCookie(cookie);
		return sessionId;
	}

	/**
	 * init cluster properties
	 */
	@Override
	public void init(FilterConfig config) throws ServletException {

		domain = config.getInitParameter("domain");
		String keyName = config.getInitParameter("key");
		if (keyName != null) {
			RedisSession.CLUSTER_KEY = keyName;
		}

		if ("false".equals(config.getInitParameter("sticky"))) {
			SESSION_STICKY = false;
		}

		String configpath = config.getInitParameter("config");
		if (configpath != null) {
			this.config = configpath;
		}
		init();
	}

	public void init() {

		ConfigLoader.load(this.config);

		CacheManager.regist("redis", new RedisCacheProvider());
	}

	@Override
	public void destroy() {

	}

}
